package com.qf.controller;

import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.qf.feign.OrderServiceFeign;
import com.qf.pojo.Order;
import com.qf.pojo.R;
import com.qf.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.print.attribute.standard.PrinterURI;
import java.util.List;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;

@RestController
@RequestMapping("/user")
//@DefaultProperties(defaultFallback = "default_fb")
public class UserController {

    /**
     * 默认降级方法要求
     *  ① 参数是空参，（可以接收异常对象）
     *  ② 返回值必须和目标方法一致
     * @return
     */
    public R default_fb(Throwable e){
        e.printStackTrace();

        return R.error().putMsg("默认降级....");
    }

//    @Autowired
//    UserService userService;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private DiscoveryClient discoveryClient;

    //注入负载均衡器对象，内部使用的Ribbon实现
    @Autowired
    private LoadBalancerClient client;

    @Autowired
    private OrderServiceFeign orderServiceFeign;

    private AtomicInteger atomicInteger = new AtomicInteger(0);

    @GetMapping("/{id}")
    /*
        这个注解内部是使用动态代理的方式，对当前受保护的findOrders方法进行了增强保护
            ① 使用内部自建线程池实现远程调用
            ② 使用try-catch捕获该方法的异常
            ③ 在执行远程调用时，会开启计时，如果远程调用的操作在规定时间内没有返回，就会抛出超时异常，不会一直等待

            上述异常最终会通过降级方法传递给我们应用

         Hystrix默认线程池大小为10，可以通过coreSize实现改变
         Hystrix默认超时时间是1s，可以通过execution.isolation.thread.timeoutInMilliseconds实现改变
     */
//    @HystrixCommand(fallbackMethod = "findOrders_fb")
//    @HystrixCommand(
//            threadPoolProperties = {@HystrixProperty(name = "coreSize",value = "5")}
//            ,commandProperties = {
//                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000"),
//                    @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "4"),
//                    @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"),
//                    @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "50"),
//            }
//    )
//    @HystrixCommand
    public R findOrders(@PathVariable("id") Integer id) throws InterruptedException {

//        int i = new Random().nextInt(10);
//        if (i>5){
//            throw new RuntimeException("error...");
//        }

        Thread.sleep(2000);

//        if (id == 1){
//            throw new RuntimeException("id:1,访问失败...");
//        }

       /* //将Ribbon负载均衡整合到RestTemplate
        R r = restTemplate.getForObject("http://QF-ORDER/order/" + id, R.class);*/

        //通过feign实现远程服务调用
        R r = orderServiceFeign.findByUid(id);

        return r;
    }

    public R findOrders_fb(Integer id,Throwable e){
        e.printStackTrace();
        return R.error().putMsg("访问服务出现异常，执行降级逻辑");
    }
}
